#pragma once

#include "Vertex.h"

namespace rt
{

	class Camera
	{
	public:
		Camera();
		virtual ~Camera();

		void SetResolution(int width, int height) { _resolutionWidth = width; _resolutionHeight = height; }

		void SetDirection(const Vec3 & dir) { _direction = dir; }

		void SetPosition(const Vec3 & pos) { _position = pos; }
		const Vec3 & GetPosition() const { return _position; }

		void SetFieldOfViewRad(float fov) { _fieldOfViewRad = fov; }
		float GetFieldOfViewRad() { return _fieldOfViewRad; }

		void GetRayGenerationInfo(Vec3 & startingRayDir,
						Vec3 & rayDirAdvanceX, Vec3 & rayDirAdvanceY) const
		{
			_direction.x = cosf(_xRot) * cosf(_yRot);
			_direction.y = sinf(_xRot);
			_direction.z = cosf(_xRot) * sinf(_yRot);

			_direction.normalize();

			_right = cross(Vec3(0.0f, 1.0f, 0.0f), _direction);
			_right.normalize();
			Vec3 _realUp = cross(_direction, _right);

			//float oneOverWidth = 1 / _resolutionWidth;

			float projWid = 1.0f * tanf(_fieldOfViewRad * 0.5f);
			float projHei = projWid * _resolutionHeight / _resolutionWidth;
			float step = projWid / _resolutionWidth;

			startingRayDir = _direction - _right * projWid * 0.5f + _realUp * projHei * 0.5f;

			rayDirAdvanceX = _right * step;
			rayDirAdvanceY = - _realUp * step;
		}

		void MoveForward(float amount)  { _position += _direction * amount * _moveSpeed; }
		void MoveBackward(float amount) { _position -= _direction * amount * _moveSpeed; }
		void MoveRight(float amount) { _position += _right * amount * _moveSpeed; }
		void MoveLeft(float amount) { _position -= _right * amount * _moveSpeed; }

		void RotateX(float amount) { _xRot += amount * _rotSpeed; }
		void RotateY(float amount) { _yRot += amount * _rotSpeed; }


	private:
		int _resolutionWidth;
		int _resolutionHeight;

		float _xRot;
		float _yRot;

		mutable Vec3 _direction;
		mutable Vec3 _right;

		Vec3 _position;


		float _fieldOfViewRad;

		float _moveSpeed;
		float _rotSpeed;

	};

}
